#include "PrecompiledHeader_Engineer.h"
#include "WPlayer.h"

/*--------------------------------------------------------------------------*/

WPlayer::WPlayer() :
	IKeyboardDriver(1000, false)
{
	this->m_playerModel = NULL;
	this->m_playerTorch = NULL;
	this->m_playerFlashlight = NULL;
	this->m_radiationLight = NULL;
	this->m_geigerSound = NULL;

	this->m_playerSpeed = 1.0f;
	this->m_staminaLevel = 1.0f;
	this->m_radiationLevel = 1.0f;
	this->m_healthLevel = 1.0f;
	this->m_lastBulletShot = 0.0f;

	this->m_bulletsLeft = WEAPON_MAGSIZE;

	this->m_cam3d = NULL;
	this->m_cameraDistance = 30.0f;

	CShell* cs = CShell::getInstance();
	cs->RegisterLuaFunction("wcure", sh::wcure);
}

/*--------------------------------------------------------------------------*/

WPlayer::~WPlayer()
{

}

/*--------------------------------------------------------------------------*/

const glm::vec3& WPlayer::GetPlayerPosition() const
{
	return this->m_playerPosition;
}

/*--------------------------------------------------------------------------*/

float WPlayer::GetPlayerRadiation() const
{
	return this->m_radiationLevel;
}

/*--------------------------------------------------------------------------*/

void WPlayer::SetPlayerRadiation(float r)
{
	if (r > 1.0f)
	{
		this->m_radiationLevel = 1.0f;
	}
	else if (r < 0.0f)
	{
		this->m_radiationLevel = 0.0f;
	}
	else
	{
		this->m_radiationLevel = r;
	}
}

/*--------------------------------------------------------------------------*/

void WPlayer::CurePlayer()
{
	this->SetPlayerRadiation(0.0f);
	this->SetPlayerStamina(1.0f);
	this->SetPlayerHealth(1.0f);
}

/*--------------------------------------------------------------------------*/

float WPlayer::GetPlayerStamina() const
{
	return this->m_staminaLevel;
}

/*--------------------------------------------------------------------------*/

void WPlayer::SetPlayerStamina(float s)
{
	if (s > 1.0f)
	{
		this->m_staminaLevel = 1.0f;
	}
	else if (s < 0.0f)
	{
		this->m_staminaLevel = 0.0f;
	}
	else
	{
		this->m_staminaLevel = s;
	}
}

/*--------------------------------------------------------------------------*/

void WPlayer::DoRadiationStuff()
{
	float radiation = WTerrain::getInstance()->GetRadiationLevel(this->m_playerPosition);

	if (radiation > rand() % 1500 / 100.0f - 0.1f)
	{
		CMixer::getInstance()->PlayNow(this->m_geigerSound);
	}

	this->SetPlayerRadiation(this->m_radiationLevel + radiation * CSdl::getInstance()->GetDeltaTime() * RADIATION_GAIN_SPEED);
	this->SetPlayerRadiation(this->m_radiationLevel - CSdl::getInstance()->GetDeltaTime() * RADIATION_CURING_SPEED);

	this->m_radiationLight->SetRadius(this->m_radiationLevel * RADIATION_LIGHT_RADIUS);
}

/*--------------------------------------------------------------------------*/

void WPlayer::DoStaminaStuff()
{
	float deltaTime = CSdl::getInstance()->GetDeltaTime();

	if (CKeyboard::getInstance()->GetKeyState(vl::Key::k_lshift) && this->m_staminaLevel > STAMINA_MINIMAL_REQUIRED_LEVEL * deltaTime)
	{
		this->m_staminaLevel -= STAMINA_MINIMAL_REQUIRED_LEVEL * deltaTime;
		this->m_playerSpeed *= STAMINA_SPEED_RATION;
	}

	this->SetPlayerStamina(this->m_staminaLevel + STAMINA_REGENERATION * deltaTime);
}

/*--------------------------------------------------------------------------*/

void WPlayer::DoLightStuff()
{
	/*-Mruganie pochodni--------------------------------------------------------*/
	float f = 0.5f + (rand() % 100) / 200.0f;
	this->m_playerTorch->SetAmbient(Color(f, f, 0.0f, 1.0));
	this->m_playerTorch->SetDiffuse(this->m_playerTorch->GetAmbient());
	this->m_playerTorch->SetRadius(3.0f + (rand() % 100) / 200.0f);

	/*-Kierunek latarki---------------------------------------------------------*/
	glm::vec2 md = CMouse::getInstance()->GetDirection();
	glm::vec3 ld = glm::vec3(md.x, md.y, 0.0f) * 10.0f + this->m_playerPosition;
	WTerrain::getInstance()->GetHeight(ld);

	this->m_playerFlashlight->SetDirection(glm::vec3(md.x, md.y, (ld.z - this->m_playerPosition.z) / 10.0f));

	if (CKeyboard::getInstance()->GetKeyState(vl::Key::k_f))
	{
		if (this->m_playerFlashlight->GetParent() != NULL)
		{
			this->m_playerFlashlight->RemoveFromTree();
		}
		else
		{
			this->m_playerFlashlight->SetParent(this->m_playerModel);
		}

		//CKeyboard::getInstance()->SetKeyState(vl::Key::k_f, false);
	}

	if (CKeyboard::getInstance()->GetKeyState(vl::Key::k_t))
	{
		if (this->m_playerTorch->GetParent() != NULL)
		{
			this->m_playerTorch->RemoveFromTree();
		}
		else
		{
			this->m_playerTorch->SetParent(this->m_playerModel);
		}

		//CKeyboard::getInstance()->SetKeyState(vl::Key::k_t, false);
	}
}

/*--------------------------------------------------------------------------*/

void WPlayer::DoCameraStuff()
{
	/*--Ustawianie kamiery------------------------------------------------------*/
	float h = this->m_cam3d->GetPosition().z;
	float wh = this->m_playerPosition.z + this->m_cameraDistance;

	this->m_cam3d->SetPosition(glm::vec3(this->m_playerPosition.x, this->m_playerPosition.y, h * 0.9f + wh * 0.1f));

	this->m_cam3d->ZeroRotate();
}

/*--------------------------------------------------------------------------*/

void WPlayer::DoMovementStuff()
{
	/*--Obsuluga klawiszy-------------------------------------------------------*/
	glm::vec3 posBackup = this->m_playerPosition;

	if (CKeyboard::getInstance()->GetKeyState(vl::Key::k_w))
	{
		this->m_playerPosition.y += this->m_playerSpeed * CSdl::getInstance()->GetDeltaTime();
	}

	if (CKeyboard::getInstance()->GetKeyState(vl::Key::k_s))
	{
		this->m_playerPosition.y -= this->m_playerSpeed * CSdl::getInstance()->GetDeltaTime();
	}

	if (CKeyboard::getInstance()->GetKeyState(vl::Key::k_a))
	{
		this->m_playerPosition.x -= this->m_playerSpeed * CSdl::getInstance()->GetDeltaTime();
	}

	if (CKeyboard::getInstance()->GetKeyState(vl::Key::k_d))
	{
		this->m_playerPosition.x += this->m_playerSpeed * CSdl::getInstance()->GetDeltaTime();
	}

	if (WTerrain::getInstance()->IsCollision(this->m_playerPosition))
	{
		this->m_playerPosition = posBackup;
	}

	//CShell::getInstance()->Execute("wcure");
// 	if (CMouse::getInstance()->GetKeyState(vl::Key::WheelUp))
// 	{
// 		this->m_cameraDistance -= 1.0f;
//
// 		if (this->m_cameraDistance < 10.0f)
// 		{
// 			this->m_cameraDistance = 10.0f;
// 		}
// 	}
//
// 	if (CMouse::getInstance()->GetKeyState(vl::Key::WheelDown))
// 	{
// 		this->m_cameraDistance += 1.0f;
//
// 		if (this->m_cameraDistance > 100.0f)
// 		{
// 			this->m_cameraDistance = 100.0f;
// 		}
// 	}
}

/*--------------------------------------------------------------------------*/

void WPlayer::DoHealthStuff()
{
	if (this->m_radiationLevel > 0.8f)
	{
		this->SetPlayerHealth(this->m_healthLevel - (CSdl::getInstance()->GetDeltaTime() * RADIATION_KILLING_RATIO));
	}
}

/*--------------------------------------------------------------------------*/

float WPlayer::GetPlayerHealth() const
{
	return this->m_healthLevel;
}

/*--------------------------------------------------------------------------*/

void WPlayer::SetPlayerHealth(float h)
{
	if (h > 1.0f)
	{
		this->m_healthLevel = 1.0f;
	}
	else if (h < 0.0f)
	{
		this->m_healthLevel = 0.0f;
	}
	else
	{
		this->m_healthLevel = h;
	}
}

/*--------------------------------------------------------------------------*/

float WPlayer::GetPlayerAmmo() const
{
	if (this->m_lastBulletShot < 0.0f)
	{
		return 1.0f + this->m_lastBulletShot / ((float)WEAPON_RELOADTIME);
	}
	else
	{
		return ((float)this->m_bulletsLeft) / ((float)WEAPON_MAGSIZE);
	}
}

/*--------------------------------------------------------------------------*/

void WPlayer::DoAmmoStuff()
{
	this->m_lastBulletShot += CSdl::getInstance()->GetDeltaTime();
}

/*--------------------------------------------------------------------------*/

void WPlayer::OnLevelLoad(const std::string& level)
{
	this->m_playerPosition = glm::vec3(525.0f, 250.0f, 0.0f);

	this->m_playerModel = new RenderableVao();
	this->m_playerModel->SetHighQualityVao(OpenGL::GetLargeSphereVao());
	this->m_playerModel->SetLowQualityVao(OpenGL::GetLargeSphereVao());
	this->m_playerModel->SetName("player");
	this->m_playerModel->SetOcclusionTestEnabled(false);
	this->m_playerModel->SetScale(1.0f);
	this->m_playerModel->SetRadius(1.0f);
	this->m_playerModel->SetCanBeActive(false);

	this->m_playerTorch = new PointLight();
	this->m_playerTorch->SetParent(this->m_playerModel);
	this->m_playerTorch->SetPosition(glm::vec3(0.0f, 0.0f, 1.2f));
	this->m_playerTorch->SetAmbient(vl::White);
	this->m_playerTorch->SetDiffuse(vl::White);
	this->m_playerTorch->SetSpecular(vl::White);
	this->m_playerTorch->SetRadius(4.0f);
	this->m_playerTorch->SetScale(4.0f);

	this->m_target = new PointLight();
	this->m_target->SetParent(CTree::getInstance()->GetRoot());
	this->m_target->SetPosition(glm::vec3());
	this->m_target->SetAmbient(vl::Blue);
	this->m_target->SetDiffuse(vl::Blue);
	this->m_target->SetSpecular(vl::Blue);
	this->m_target->SetRadius(16.0f);
	this->m_target->SetScale(16.0f);

	this->m_radiationLight = new PointLight();
	this->m_radiationLight->SetParent(this->m_playerModel);
	this->m_radiationLight->SetPosition(glm::vec3(0.0f, 0.0f, 1.2f));
	this->m_radiationLight->SetAmbient(vl::Green);
	this->m_radiationLight->SetDiffuse(vl::Green);
	this->m_radiationLight->SetSpecular(vl::Green);
	this->m_radiationLight->SetRadius(4.0f);

	CResources::getInstance()->Get("geiger", &this->m_geigerSound);
	CResources::getInstance()->Get("gunshot", &this->m_gunshotSound);
	CResources::getInstance()->Get("reload", &this->m_reloadSound);
	CResources::getInstance()->Get("gong", &this->m_gongSound);
	CResources::getInstance()->Get("death", &this->m_deathSound);

	this->m_playerFlashlight = new SpotLight();
	this->m_playerFlashlight->SetParent(this->m_playerModel);
	this->m_playerFlashlight->SetPosition(glm::vec3(0.0f, 0.0f, 1.2f));
	this->m_playerFlashlight->SetAmbient(Color(0.5f, 0.5f, 0.5f));
	this->m_playerFlashlight->SetDiffuse(vl::White);
	this->m_playerFlashlight->SetSpecular(vl::White);
	this->m_playerFlashlight->SetRadius(30.0f);
	this->m_playerFlashlight->SetAngleCos(0.8f);

	this->m_cam3d = CCamera::getInstance()->GetFCamera();

	this->m_playerModel->SetParent(CTree::getInstance()->GetRoot());
}

/*--------------------------------------------------------------------------*/

void WPlayer::OnLevelUnload()
{
	CTree::getInstance()->DeleteObject(this->m_playerModel);
}

/*--------------------------------------------------------------------------*/

void WPlayer::OnLevelCalc()
{
	CKeyboard::getInstance()->AddKeyboardDriver(this);

	/*--Przesuniecie przynaleznosci playera-------------------------------------*/
	WTerrain::getInstance()->GetHeight(this->m_playerPosition);
	this->m_playerModel->SetPosition(this->m_playerPosition);

	this->m_playerSpeed = PLAYER_WALK_SPEED * 4;
	this->DoRadiationStuff();
	this->DoStaminaStuff();
	this->DoLightStuff();
	this->DoCameraStuff();
	this->DoMovementStuff();
	this->DoHealthStuff();
	this->DoAmmoStuff();

	if (this->m_healthLevel == 0.0f)
	{
		CMixer::getInstance()->PlayNow(this->m_deathSound);
		CShell::getInstance()->Execute("loadscript('start_splashscreen')");
	}

	if (glm::distance(this->m_playerPosition, this->m_target->GetPosition()) < 16.0f)
	{
		CMixer::getInstance()->PlayNow(this->m_gongSound);
		this->NextTarget();
	}
}

/*--------------------------------------------------------------------------*/

void WPlayer::OnKeyboardAction()
{
	if (CMouse::getInstance()->GetKeyState(vl::Key::LMB) && this->m_lastBulletShot > WEAPON_PAUSETIME && this->m_bulletsLeft > 0)
	{
		this->m_lastBulletShot = 0.0f;
		this->m_bulletsLeft -= 1;

		CMixer::getInstance()->PlayNow(this->m_gunshotSound);
		WBullets::getInstance()->AddBullet(this->m_playerPosition,
		                                   glm::vec3(CMouse::getInstance()->GetDirection(), 0.0f) * 100.0f,
		                                   5.0f,
		                                   vl::Yellow);
	}

	if (CKeyboard::getInstance()->GetKeyState(vl::Key::k_r) && this->m_lastBulletShot >= 0.0f)
	{
		CMixer::getInstance()->PlayNow(this->m_reloadSound);

		this->m_bulletsLeft = WEAPON_MAGSIZE;
		this->m_lastBulletShot = -WEAPON_RELOADTIME;
		CKeyboard::getInstance()->SetKeyState(vl::Key::k_r, false);
	}
}

/*--------------------------------------------------------------------------*/

const glm::vec3& WPlayer::GetTarget() const
{
	return this->m_target->GetPosition();
}

/*--------------------------------------------------------------------------*/

void WPlayer::NextTarget()
{
	glm::vec3 pos = glm::vec3(rand() % 1000, rand() % 1000, 0.0f);
	WTerrain::getInstance()->GetHeight(pos);

	this->m_target->SetPosition(pos);
}

/*--------------------------------------------------------------------------*/

void sh::wcure()
{
	WPlayer::getInstance()->CurePlayer();
}

/*--------------------------------------------------------------------------*/